﻿namespace PugLib.UnitTest
{
	using System.Collections;
	using System.Collections.Generic;
	using System.Linq;

	using Microsoft.VisualStudio.TestTools.UnitTesting;

	using PugLib.Collections;

	/// <summary>
	/// Unit tests against ValidationDictionary container class.
	/// </summary>
	[TestClass]
	public class ValidationDictionaryTest
	{
		/// <summary>
		/// Test IDictionary.Values property.
		/// </summary>
		[TestMethod]
		public void ValuesTest()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };
			ICollection<string> valuesList1 = dict1.Values;
			string[] expectedList1 = new[] {"1", "2", "3"};
			Assert.AreEqual(expectedList1.Count(), valuesList1.Count, "Value count mismatch");
			Assert.AreEqual(expectedList1.Count(), valuesList1.Count(), "Value count mismatch");
			Assert.IsTrue(expectedList1.All(valuesList1.Contains), "Values mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };
			ICollection<string> valuesList2 = dict2.Values;
			string[] expectedList2 = new string[] {};
			Assert.AreEqual(expectedList2.Count(), valuesList2.Count, "Value count mismatch");
			Assert.AreEqual(expectedList2.Count(), valuesList2.Count(), "Value count mismatch");
			Assert.IsTrue(expectedList2.All(valuesList2.Contains), "Values mismatch");
		}

		/// <summary>
		/// Test IDictionary.Keys property.
		/// </summary>
		[TestMethod]
		public void KeysTest()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };
			ICollection<string> keysList1 = dict1.Keys;
			string[] expectedList1 = new[] {"a", "b", "c"};
			Assert.AreEqual(expectedList1.Count(), keysList1.Count, "Key count mismatch");
			Assert.AreEqual(expectedList1.Count(), keysList1.Count(), "Key count mismatch");
			Assert.IsTrue(expectedList1.All(keysList1.Contains), "Keys mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };
			ICollection<string> keysList2 = dict2.Keys;
			string[] expectedList2 = new string[] {};
			Assert.AreEqual(expectedList2.Count(), keysList2.Count, "Key count mismatch");
			Assert.AreEqual(expectedList2.Count(), keysList2.Count(), "Key count mismatch");
			Assert.IsTrue(expectedList2.All(keysList2.Contains), "Keys mismatch");
		}

		/// <summary>
		/// Test IDictionary[] property.
		/// </summary>
		[TestMethod]
		public void ItemTest()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };
			Assert.AreEqual("1", dict1["a"], "Item mismatch");
			Assert.AreEqual("2", dict1["b"], "Item mismatch");
			Assert.AreEqual("3", dict1["c"], "Item mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };
			try
			{
				Assert.AreNotEqual("1", dict2["a"], "Key was not invalidated");
				Assert.Fail("Item returned an unexpected value");
			}
			catch (KeyNotFoundException)
			{
			}
			try
			{
				Assert.AreNotEqual("2", dict2["b"], "Key was not invalidated");
				Assert.Fail("Item returned an unexpected value");
			}
			catch (KeyNotFoundException)
			{
			}
			try
			{
				Assert.AreNotEqual("3", dict2["c"], "Key was not invalidated");
				Assert.Fail("Item returned an unexpected value");
			}
			catch (KeyNotFoundException)
			{
			}
		}

		/// <summary>
		/// Test ICollection.Count property.
		/// </summary>
		[TestMethod]
		public void CountTest()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };
			Assert.AreEqual(3, dict1.Count, "Count mismatch");
			Assert.AreEqual(3, dict1.Count(), "Count mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };
			Assert.AreEqual(0, dict2.Count, "Count mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count mismatch");
		}

		/// <summary>
		/// Test IDictionary.TryGetValues() method.
		/// </summary>
		[TestMethod]
		public void TryGetValueTest()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			string value1;
			Assert.IsTrue(dict1.TryGetValue("a", out value1), "TryGetValue failed");
			Assert.AreEqual("1", value1, "Value mismatch");
			Assert.IsTrue(dict1.TryGetValue("b", out value1), "TryGetValue failed");
			Assert.AreEqual("2", value1, "Value mismatch");
			Assert.IsTrue(dict1.TryGetValue("c", out value1), "TryGetValue failed");
			Assert.AreEqual("3", value1, "Value mismatch");

			Assert.IsFalse(dict1.TryGetValue("z", out value1), "TryGetValue failed");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			string value2;
			Assert.IsFalse(dict2.TryGetValue("a", out value2), "TryGetValue failed");
			Assert.AreEqual("1", value2, "Value mismatch");
			Assert.IsFalse(dict2.TryGetValue("b", out value2), "TryGetValue failed");
			Assert.AreEqual("2", value2, "Value mismatch");
			Assert.IsFalse(dict2.TryGetValue("c", out value2), "TryGetValue failed");
			Assert.AreEqual("3", value2, "Value mismatch");

			Assert.IsFalse(dict1.TryGetValue("z", out value2), "TryGetValue failed");
		}

		/// <summary>
		/// Test IEnumerable.GetEnumerator() generic method.
		/// </summary>
		[TestMethod]
		public void GetEnumeratorTest1()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			int count1 = 0;
			foreach (KeyValuePair<string, string> pair in dict1)
			{
				Assert.AreEqual(dict1[pair.Key], pair.Value, "Item value mismatch");
				count1++;
			}
			Assert.AreEqual(3, count1, "Enumerator count mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			int count2 = 0;
			foreach (KeyValuePair<string, string> pair in dict2)
			{
				Assert.AreEqual(dict2[pair.Key], pair.Value, "Item value mismatch");
				count2++;
			}
			Assert.AreEqual(0, count2, "Enumerator count mismatch");
		}

		/// <summary>
		/// Test IEnumerable.GetEnumerator() method.
		/// </summary>
		[TestMethod]
		public void GetEnumeratorTest2()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			int count1 = 0;
			foreach (object item in (IEnumerable)dict1)
			{
				Assert.IsInstanceOfType(item, typeof(KeyValuePair<string, string>), "Item type mismatch");
				KeyValuePair<string, string> pair = (KeyValuePair<string, string>)item;
				Assert.AreEqual(dict1[pair.Key], pair.Value, "Item value mismatch");
				count1++;
			}
			Assert.AreEqual(3, count1, "Enumerator count mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			int count2 = 0;
			foreach (object item in (IEnumerable)dict2)
			{
				Assert.IsInstanceOfType(item, typeof(KeyValuePair<string, string>), "Item type mismatch");
				KeyValuePair<string, string> pair = (KeyValuePair<string, string>)item;
				Assert.AreEqual(dict2[pair.Key], pair.Value, "Item value mismatch");
				count2++;
			}
			Assert.AreEqual(0, count2, "Enumerator count mismatch");
		}

		/// <summary>
		/// Test IDictionary.Remove() method.
		/// </summary>
		[TestMethod]
		public void RemoveTest1()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			Assert.IsTrue(dict1.Remove("a"), "Remove failed");
			Assert.IsFalse(dict1.Remove("a"), "Attempted remove of already removed key failed");
			Assert.AreEqual(2, dict1.Count, "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Count(), "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Values.Count(), "Count after remove mismatch");

			Assert.IsTrue(dict1.Remove("b"), "Remove failed");
			Assert.IsFalse(dict1.Remove("b"), "Attempted remove of already removed key failed");
			Assert.AreEqual(1, dict1.Count, "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Count(), "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Values.Count(), "Count after remove mismatch");

			Assert.IsTrue(dict1.Remove("c"), "Remove failed");
			Assert.IsFalse(dict1.Remove("c"), "Attempted remove of already removed key failed");
			Assert.AreEqual(0, dict1.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict1.Remove("z"), "Attempted remove of nonexistant key failed");
			Assert.AreEqual(0, dict1.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Values.Count(), "Count after remove mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			Assert.IsFalse(dict2.Remove("a"), "Remove failed");
			Assert.IsFalse(dict2.Remove("a"), "Attempted remove of already removed key failed");
			Assert.AreEqual(0, dict2.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict2.Remove("b"), "Remove failed");
			Assert.IsFalse(dict2.Remove("b"), "Attempted remove of already removed key failed");
			Assert.AreEqual(0, dict2.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict2.Remove("c"), "Remove failed");
			Assert.IsFalse(dict2.Remove("c"), "Attempted remove of already removed key failed");
			Assert.AreEqual(0, dict2.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict2.Remove("z"), "Attempted remove of nonexistant key failed");
			Assert.AreEqual(0, dict2.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after remove mismatch");
		}

		/// <summary>
		/// Test ICollection.Remove() method.
		/// </summary>
		[TestMethod]
		public void RemoveTest2()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("a", "999")), "Attempted remove of nonexistant pair failed");
			Assert.IsTrue(dict1.Remove(new KeyValuePair<string, string>("a", "1")), "Remove failed");
			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("a", "1")), "Attempted remove of already removed pair failed");
			Assert.AreEqual(2, dict1.Count, "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Count(), "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(2, dict1.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("b", "999")), "Attempted remove of nonexistant pair failed");
			Assert.IsTrue(dict1.Remove(new KeyValuePair<string, string>("b", "2")), "Remove failed");
			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("b", "2")), "Attempted remove of already removed pair failed");
			Assert.AreEqual(1, dict1.Count, "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Count(), "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(1, dict1.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("c", "999")), "Attempted remove of nonexistant pair failed");
			Assert.IsTrue(dict1.Remove(new KeyValuePair<string, string>("c", "3")), "Remove failed");
			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("c", "3")), "Attempted remove of already removed pair failed");
			Assert.AreEqual(0, dict1.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("z", "26")), "Attempted remove of nonexistant pair failed");
			Assert.AreEqual(0, dict1.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict1.Values.Count(), "Count after remove mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("a", "999")), "Attempted remove of nonexistant pair failed");
			Assert.IsFalse(dict2.Remove(new KeyValuePair<string, string>("a", "1")), "Remove failed");
			Assert.IsFalse(dict2.Remove(new KeyValuePair<string, string>("a", "1")), "Attempted remove of already removed pair failed");
			Assert.AreEqual(0, dict2.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("b", "999")), "Attempted remove of nonexistant pair failed");
			Assert.IsFalse(dict2.Remove(new KeyValuePair<string, string>("b", "2")), "Remove failed");
			Assert.IsFalse(dict2.Remove(new KeyValuePair<string, string>("b", "2")), "Attempted remove of already removed pair failed");
			Assert.AreEqual(0, dict2.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict1.Remove(new KeyValuePair<string, string>("c", "999")), "Attempted remove of nonexistant pair failed");
			Assert.IsFalse(dict2.Remove(new KeyValuePair<string, string>("c", "3")), "Remove failed");
			Assert.IsFalse(dict2.Remove(new KeyValuePair<string, string>("c", "3")), "Attempted remove of already removed pair failed");
			Assert.AreEqual(0, dict2.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after remove mismatch");

			Assert.IsFalse(dict2.Remove(new KeyValuePair<string, string>("z", "26")), "Attempted remove of nonexistant pair failed");
			Assert.AreEqual(0, dict2.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after remove mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after remove mismatch");
		}

		/// <summary>
		/// Test ICollection.CopyTo() method.
		/// </summary>
		[TestMethod]
		public void CopyToTest()
		{
			KeyValuePair<string, string>[] items1 = new[]
			                                        {
			                                        	new KeyValuePair<string, string>("a", "1"),
			                                        	new KeyValuePair<string, string>("b", "2"),
			                                        	new KeyValuePair<string, string>("c", "3")
			                                        };
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true);

			// Populate dictionary
			foreach (KeyValuePair<string, string> item in items1)
			{
				dict1.Add(item);
			}

			// CopyTo array
			KeyValuePair<string, string>[] items2 = new KeyValuePair<string, string>[dict1.Count];
			dict1.CopyTo(items2, 0);

			// Compare array
			Assert.AreEqual(items2.Length, items1.Length, "Array length mismatch");
			Assert.IsTrue(items1.All(pair => items2.Contains(pair)), "Array values mismatch");
		}

		/// <summary>
		/// Test IDictionary.ContainsKey() method.
		/// </summary>
		[TestMethod]
		public void ContainsKeyTest()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			Assert.IsTrue(dict1.ContainsKey("a"), "ContainsKey failed");
			Assert.IsTrue(dict1.ContainsKey("b"), "ContainsKey failed");
			Assert.IsTrue(dict1.ContainsKey("c"), "ContainsKey failed");
			Assert.IsFalse(dict1.ContainsKey("z"), "ContainsKey failed");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			Assert.IsFalse(dict2.ContainsKey("a"), "ContainsKey failed");
			Assert.IsFalse(dict2.ContainsKey("b"), "ContainsKey failed");
			Assert.IsFalse(dict2.ContainsKey("c"), "ContainsKey failed");
			Assert.IsFalse(dict2.ContainsKey("z"), "ContainsKey failed");
		}

		/// <summary>
		/// Test ICollection.Contains() method.
		/// </summary>
		[TestMethod]
		public void ContainsTest()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			Assert.IsTrue(dict1.Contains(new KeyValuePair<string, string>("a", "1")), "Contains failed");
			Assert.IsFalse(dict1.Contains(new KeyValuePair<string, string>("a", "999")), "Contains failed on nonexistant pair");
			Assert.IsTrue(dict1.Contains(new KeyValuePair<string, string>("b", "2")), "Contains failed");
			Assert.IsFalse(dict1.Contains(new KeyValuePair<string, string>("b", "999")), "Contains failed on nonexistant pair");
			Assert.IsTrue(dict1.Contains(new KeyValuePair<string, string>("c", "3")), "Contains failed");
			Assert.IsFalse(dict1.Contains(new KeyValuePair<string, string>("c", "999")), "Contains failed on nonexistant pair");
			Assert.IsFalse(dict1.Contains(new KeyValuePair<string, string>("z", "26")), "Contains failed on nonexistant pair");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("a", "1")), "Contains failed on invalidated pair");
			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("a", "999")), "Contains failed on nonexistant pair");
			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("b", "2")), "Contains failed on invalidated pair");
			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("b", "999")), "Contains failed on nonexistant pair");
			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("c", "3")), "Contains failed on invalidated pair");
			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("c", "999")), "Contains failed on nonexistant pair");
			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("z", "26")), "Contains failed on nonexistant pair");
		}

		/// <summary>
		/// Test ICollection.Clear() method.
		/// </summary>
		[TestMethod]
		public void ClearTest()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			dict1.Clear();
			Assert.AreEqual(0, dict1.Count, "Count after clear mismatch");
			Assert.AreEqual(0, dict1.Count(), "Count after clear mismatch");
			Assert.AreEqual(0, dict1.Keys.Count, "Count after clear mismatch");
			Assert.AreEqual(0, dict1.Keys.Count(), "Count after clear mismatch");
			Assert.AreEqual(0, dict1.Values.Count, "Count after clear mismatch");
			Assert.AreEqual(0, dict1.Values.Count(), "Count after clear mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			dict2.Clear();
			Assert.AreEqual(0, dict2.Count, "Count after clear mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after clear mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after clear mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after clear mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after clear mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after clear mismatch");
		}

		/// <summary>
		/// Test IDictionary.Add() method.
		/// </summary>
		[TestMethod]
		public void AddTest1()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			dict1.Add("d", "4");
			Assert.AreEqual("4", dict1["d"], "Item value after add mismatch");
			Assert.IsTrue(dict1.ContainsKey("d"), "ContainsKey after add failed");
			Assert.IsTrue(dict1.Contains(new KeyValuePair<string, string>("d", "4")), "Contains after add failed");
			Assert.AreEqual(4, dict1.Count, "Count after add mismatch");
			Assert.AreEqual(4, dict1.Count(), "Count after add mismatch");
			Assert.AreEqual(4, dict1.Keys.Count, "Count after add mismatch");
			Assert.AreEqual(4, dict1.Keys.Count(), "Count after add mismatch");
			Assert.AreEqual(4, dict1.Values.Count, "Count after add mismatch");
			Assert.AreEqual(4, dict1.Values.Count(), "Count after add mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			dict2.Add("d", "4");
			try
			{
				Assert.AreNotEqual("4", dict2["d"], "Key was not invalidated");
				Assert.Fail("Item returned an unexpected value");
			}
			catch (KeyNotFoundException)
			{
			}
			Assert.IsFalse(dict2.ContainsKey("d"), "ContainsKey after add failed");
			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("d", "4")), "Contains after add failed");
			Assert.AreEqual(0, dict2.Count, "Count after add mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after add mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after add mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after add mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after add mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after add mismatch");
		}

		/// <summary>
		/// Test ICollection.Add() method.
		/// </summary>
		[TestMethod]
		public void AddTest2()
		{
			ValidationDictionary<string, string> dict1 = new ValidationDictionary<string, string>(key => true)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			dict1.Add(new KeyValuePair<string, string>("d", "4"));
			Assert.AreEqual("4", dict1["d"], "Item value after add mismatch");
			Assert.IsTrue(dict1.ContainsKey("d"), "ContainsKey after add failed");
			Assert.IsTrue(dict1.Contains(new KeyValuePair<string, string>("d", "4")), "Contains after add failed");
			Assert.AreEqual(4, dict1.Count, "Count after add mismatch");
			Assert.AreEqual(4, dict1.Count(), "Count after add mismatch");
			Assert.AreEqual(4, dict1.Keys.Count, "Count after add mismatch");
			Assert.AreEqual(4, dict1.Keys.Count(), "Count after add mismatch");
			Assert.AreEqual(4, dict1.Values.Count, "Count after add mismatch");
			Assert.AreEqual(4, dict1.Values.Count(), "Count after add mismatch");

			ValidationDictionary<string, string> dict2 = new ValidationDictionary<string, string>(key => false)
			                                             {
			                                             	{"a", "1"},
			                                             	{"b", "2"},
			                                             	{"c", "3"}
			                                             };

			dict2.Add(new KeyValuePair<string, string>("d", "4"));
			try
			{
				Assert.AreNotEqual("4", dict2["d"], "Key was not invalidated");
				Assert.Fail("Item returned an unexpected value");
			}
			catch (KeyNotFoundException)
			{
			}
			Assert.IsFalse(dict2.ContainsKey("d"), "ContainsKey after add failed");
			Assert.IsFalse(dict2.Contains(new KeyValuePair<string, string>("d", "4")), "Contains after add failed");
			Assert.AreEqual(0, dict2.Count, "Count after add mismatch");
			Assert.AreEqual(0, dict2.Count(), "Count after add mismatch");
			Assert.AreEqual(0, dict2.Keys.Count, "Count after add mismatch");
			Assert.AreEqual(0, dict2.Keys.Count(), "Count after add mismatch");
			Assert.AreEqual(0, dict2.Values.Count, "Count after add mismatch");
			Assert.AreEqual(0, dict2.Values.Count(), "Count after add mismatch");
		}
	}
}